package biolabs.query;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import biolabs.core.BioObject;

abstract class NumericPredicate implements Predicate {

	private final Expression a, b;

	public NumericPredicate(Expression a, Expression b) {
		if(a == null || b == null)
			throw new NullPointerException();
		this.a = a;
		this.b = b;
	}

	@Override
	public boolean eval(BioObject obj) {
		Object valA = a.eval(obj);
		Object valB = b.eval(obj);

		if(valA == null || valB == null)
			return false;

		BigDecimal bigA = toBigDecimal(a);
		BigDecimal bigB = toBigDecimal(b);

		if(bigA == null || bigB == null)
			return false;

		return evalNumbers(bigA, bigB);
	}

	public abstract boolean evalNumbers(BigDecimal a, BigDecimal b);

	static BigDecimal toBigDecimal(Object o) {
		if(!(o instanceof Number))
			return null;
		Number a = (Number)o;
		if(
				a instanceof Long ||
				a instanceof Integer ||
				a instanceof Short ||
				a instanceof Byte ||
				a instanceof AtomicLong ||
				a instanceof AtomicInteger
		) {
			return new BigDecimal(a.longValue());
		} else if(
				a instanceof Double ||
				a instanceof Float
		) {
			return new BigDecimal(a.doubleValue());
		} else if(a instanceof BigInteger) {
			return new BigDecimal((BigInteger)a);
		} else if(a instanceof BigDecimal) {
			return (BigDecimal)a;
		} else {
			return null;
		}
	}

}
